﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Convertor.Interface;
using Wpf.CommonTools.SystemExtension;
using System.Windows;
using System.Collections;

namespace Convertor.Plugin.InputAndOutput
{
    public class Plugin : PluginBase
    {
        #region Static Func

        static string[] LanguagePaths = new string[] { @"Convertor.Plugin.InputAndOutput;component\Assets\Lang\StringResource.zh.xaml", @"Convertor.Plugin.InputAndOutput;component\Assets\Lang\StringResource.en.xaml" };

        static Plugin()
        {
            foreach (string path in LanguagePaths)
            {
                ResourceDictionary resourceDictionary = new ResourceDictionary();
                resourceDictionary.Source = new Uri(path, UriKind.Relative);
                Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
            }
        }

        private static List<MemoryContent> memory = new List<MemoryContent>();

        public static List<MemoryContent> Memory
        {
            get { return Plugin.memory; }
        }

        #endregion

        #region IPluginInfo 成员

        public override string Name
        {
            get { return UILanguage.FindResource("PluginType_System") + " - " + UILanguage.FindResource("Plugin_InputAndOutput_Name"); }
        }

        public override string Description
        {
            get { return UILanguage.FindResource("Plugin_InputAndOutput_Desc"); }
        }

        

        

        #endregion

        #region IConvertParamters 成员

        public override IConvertParamters Output(IConvertParamters content)
        {
            IConvertParamters outputContent = null;
            string logStr = string.Empty;
            if (config.OperateTarget == OutputTypes.InputContent)
            {
                switch ((OperateInputTypes)config.OperateType.Value)
                {
                    default:
                    case OperateInputTypes.CombineWithOutput:
                        string value = string.Format("{0}{1}{2}", content.LastInputContent, config.OperateText, content.OutputContent);
                        outputContent = new ConvertParamters(value, content.OutputContent);
                        break;
                    case OperateInputTypes.CompareToOutput:
                        object temp = compare(content.LastInputContent, content.OutputContent);
                        logStr = (UILanguage.TryFindResource("Return: ") + temp);
                        outputContent = new ConvertParamters(content.LastInputContent, temp);
                        break;
                    case OperateInputTypes.PopFromMemory:
                        object popObject = popFromMemory();
                        outputContent = new ConvertParamters(popObject, content.OutputContent);
                        break;
                    case OperateInputTypes.PushToMemory:
                        pushToMemory(content.LastInputContent);
                        outputContent = content;
                        break;
                    case OperateInputTypes.ReplaceWithOutput:
                        outputContent = new ConvertParamters(content.OutputContent, content.OutputContent);
                        break;
                    case OperateInputTypes.RevertWithOutput:
                        outputContent = new ConvertParamters(content.OutputContent, content.LastInputContent);
                        break;
                    case OperateInputTypes.SetAs:
                        outputContent = new ConvertParamters(config.ReplaceText, content.OutputContent);
                        break;
                }
            }
            else
            {
                switch ((OperateOutputTypes)config.OperateType.Value)
                {
                    default:
                    case OperateOutputTypes.CombineWithInput:
                        string value = string.Format("{0}{1}{2}", content.OutputContent, config.OperateText, content.LastInputContent);
                        outputContent = new ConvertParamters(content.LastInputContent, value);
                        break;
                    case OperateOutputTypes.CompareToInput:
                        object temp = compare(content.OutputContent, content.LastInputContent);
                        logStr = (UILanguage.TryFindResource("Return: ") + temp);
                        outputContent = new ConvertParamters(content.LastInputContent, temp);
                        break;
                    case OperateOutputTypes.PopFromMemory:
                        object popObject = popFromMemory();
                        outputContent = new ConvertParamters(content.LastInputContent, popObject);
                        break;
                    case OperateOutputTypes.PushToMemory:
                        pushToMemory(content.OutputContent);
                        outputContent = content;
                        break;
                    case OperateOutputTypes.ReplaceWithInput:
                        outputContent = new ConvertParamters(content.LastInputContent, content.LastInputContent);
                        break;
                    case OperateOutputTypes.RevertWithInput:
                        outputContent = new ConvertParamters(content.OutputContent, content.LastInputContent);
                        break;
                    case OperateOutputTypes.SetAs:
                        outputContent = new ConvertParamters(content.LastInputContent, config.ReplaceText);
                        break;
                }
            }
            if (string.IsNullOrEmpty(logStr))
            {
                if (Log != null) { Log(this, config.ToolTip, LogTypes.Normal); }
            }
            else
            {
                if (Log != null) { Log(this, config.ToolTip, LogTypes.Normal); }
                if (Log != null) { Log(this, logStr, LogTypes.HidePluginName); }
            }
            return outputContent;
        }

        private void pushToMemory(object @object)
        {
            var a = memory.Select((v, i) => new { MContent = v, Index = i }).FirstOrDefault(p => p.MContent.Name == config.UniqName);
            int index = a == null ? -1 : a.Index;
            if (index >= 0)
            {
                memory[0].Content = @object;
            }
            else
            {
                memory.Add(new MemoryContent() { Name = config.UniqName, Content = @object });
            }
        }

        private object popFromMemory()
        {
            var a = memory.Select((v, i) => new { MContent = v, Index = i }).FirstOrDefault(p => p.MContent.Name == config.UniqName);
            int index = (a == null) ? -1 : a.Index;
            object outTemp = index >= 0
                ? outTemp = memory[0].Content
                : outTemp = "Object.NULL";
            return outTemp;
        }

        private bool compare(object c1, object c2)
        {
            bool b = false;
            int a;

            a= string.Compare(c1.ToString(), c2.ToString());

            if (config.CompareType.HasFlag(CompareTypes.IsEqual))
            {
                b = b | a == 0;
            }
            if (config.CompareType.HasFlag(CompareTypes.IsNotEqual))
            {
                b = b | a != 0;
            }
            if (config.CompareType.HasFlag(CompareTypes.Great))
            {

                b = b | a > 0;
            }
            if (config.CompareType.HasFlag(CompareTypes.Less))
            {
                b = b | a < 0;
            }
            return b;
        }

        #endregion

        #region IPluginConfigForm 成员

        public override PluginConfigForm ConfigForm
        {
            get { return new ConfigForm(); }
        }

        #endregion

        #region IPluginConfig 成员

        private ConfigContent config;
        public override object Config
        {
            get { return config; }
            set { config = (value as ConfigContent) ?? new ConfigContent(); }
        }

        #endregion

    }
}
